﻿using Microsoft.AspNetCore.Mvc;
using PMS.Core.Configuration.CommonEnumConfigs;
using PMS.Data.Entities.Customers;
using PMS.Data.Entities.Settings;
using PMS.Services.Authentication;
using PMS.Services.EntityServices.Common;
using PMS.Services.EntityServices.Customers;
using PMS.Services.EntityServices.Messages;
using PMS.Services.SharedKernel;
using PMS.Services.Utils;
using PMS.Services.Utils.Events;
using PMS.Web.Factories.Customers;
using PMS.Web.Framework.Controllers;
using PMS.Web.Framework.StartupCfgs.StartupSetups;
using PMS.Web.Models.Customers;
using System;

namespace PMS.Web.Controllers.Frontend.Customer
{
    public class CustomerController : BaseController
    {
        #region Fields
        private readonly CustomerSettings _customerSettings;
        private readonly IWorkContext _workContext;
        private readonly ICustomerService _customerService;
        private readonly IEventDispatcher _eventDispatcher;
        private readonly ICustomerModelFactory _customerModelFactory;
        private readonly IAuthenticationProvider _authenticationProvider;
        private readonly IWorkflowMessageService _workflowMessageService;
        private readonly IGenericAttributeService _genericAttributeService;
        #endregion

        #region Ctor
        public CustomerController(CustomerSettings customerSettings,
            IWorkContext workContext,
            ICustomerService customerService,
            IEventDispatcher eventDispatcher,
            ICustomerModelFactory customerModelFactory,
            IAuthenticationProvider authenticationProvider,
            IWorkflowMessageService workflowMessageService,
            IGenericAttributeService genericAttributeService)
        {
            _customerSettings = customerSettings;
            _workContext = workContext;
            _customerService = customerService;
            _eventDispatcher = eventDispatcher;
            _customerModelFactory = customerModelFactory;
            _authenticationProvider = authenticationProvider;
            _workflowMessageService = workflowMessageService;
            _genericAttributeService = genericAttributeService;
        }
        #endregion

        #region Methods

        #region Customer Register
        /// <summary>
        /// 用户注册页
        /// </summary>
        /// <returns></returns>
        public virtual IActionResult RegisterView()
        {
            //check whether registration is allowed
            if (_customerSettings.UserRegistrationType == UserRegistrationType.Disabled)
                return RedirectToAction("RegisterDisallowdView", "Customer");

            var model = new RegisterModel();
            model = _customerModelFactory.PrepareRegisterModel(model);
            return View(model);
        }

        /// <summary>
        /// 当注册通道关闭时显示
        /// </summary>
        /// <returns></returns>
        public virtual IActionResult RegisterDisallowdView()
        {
            ViewBag.WorkContext = _workContext;
            return View();
        }

        /// <summary>
        /// 当CustomerSetting.UserRegisterType为EmailValidation时，账户注册启用邮箱验证功能
        /// 当用户接收到邮件并点击链接进行验证后，对注册用户进行账号激活操作
        /// </summary>
        /// <param name="token"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        public virtual IActionResult AccountActivationView(string token, Guid guid)
        {
            var customer = _customerService.GetCustomerByGuid(guid);
            if (customer == null)
                return RedirectToRoute("HomePage");

            var activeResult = new AccountActivationModel
            {
                Success = false,
                Result = string.Empty
            };
            ViewBag.WorkContext = _workContext;
            var cToken = _genericAttributeService.GetAttribute<string>(customer, CustomerDefaultConfigs.AccountActivationTokenAttribute);
            if (string.IsNullOrEmpty(cToken))
            {
                activeResult.Result = "账号已激活,请勿重复操作";
                return View(activeResult);
            }
            if (!cToken.Equals(token, StringComparison.InvariantCultureIgnoreCase))
                return RedirectToRoute("HomePage");

            var registeredRole = _customerService.GetCustomerRoleByRoleType(RoleType.Guests);
            if (registeredRole == null)
            {
                activeResult.Result = "账号激活失败：无法分配用户组,请联系系统管理员";
                return View(activeResult);
            }
                 
            //activate user account
            customer.IsActive = true;
            customer.UpdatedOnTimeUtc = customer.LastActivityTimeUtc = DateTime.UtcNow;
            _customerService.UpdateCustomer(customer);
            
            _customerService.AddCustomerRoleMapping(new CustomerCustomerRoleMapping { CustomerId = customer.Id, CustomerRoleId = registeredRole.Id });
            _genericAttributeService.SaveAttribute(customer, CustomerDefaultConfigs.AccountActivationTokenAttribute, "");
            //send welcome message
            _workflowMessageService.SendCustomerRegisteredWelcomeEmail(customer);

            //raise event       
            //reserved Event for further CustomerActivatedEvent
            _eventDispatcher.Dispatch(new CustomerActivatedEvent(customer));

            //Signout current logged in Customer if another account loggedin
            if(_workContext.CurrentCustomer != null)
            {
                _authenticationProvider.AuthServcice.SignOut();
                //raise logged out event       
                _eventDispatcher.Dispatch(new CustomerLoggedOutEvent(_workContext.CurrentCustomer));
            }
            activeResult.Success = true;
            activeResult.Result = "账号激活成功,请您重新登录新账号,祝您生活愉快";
            return View(activeResult);
        }

        /// <summary>
        /// 已登录用户绑定第三方授权登录账户成功页面
        /// </summary>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public IActionResult BindExternalAccountWithUserSuccess(string returnUrl, Guid customerGuid)
        {
            if (_workContext.CurrentCustomer == null && !customerGuid.Equals(Guid.Empty))
            {
                _workContext.CurrentCustomer = _customerService.GetCustomerByGuid(customerGuid);
            }
            ViewBag.returnUrl = returnUrl;
            return View(_workContext.CurrentCustomer);
        }
        #endregion

        #region MyAccount ChangeCustomerPassword

        public virtual IActionResult ChangePasswordView()
        {
            if (!_customerService.IsRegistered(_workContext.CurrentCustomer))
                return new RedirectResult(DefaultRoutePath.LoginPath);

            var model = _customerModelFactory.PrepareChangePasswordModel(_workContext.CurrentCustomer.Id);

            //display the cause of the change password 
            if (_customerService.PasswordIsExpired(_workContext.CurrentCustomer) > 0)
                ModelState.AddModelError(string.Empty, "您的账号密码已长时间未更新,为保障您的账户安全,建议您更换账户密码。");

            return View(model);
        }
        #endregion

        #region Password recovery

        /// <summary>
        /// 忘记密码页
        /// </summary>
        /// <returns></returns>
        public virtual IActionResult PasswordRecoveryView()
        {
            var model = _customerModelFactory.PreparePasswordRecoveryModel();

            return View(model);
        }

        /// <summary>
        /// 通过邮件/手机短信等方式进入密码重置页
        /// </summary>
        /// <param name="token"></param>
        /// <param name="email"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        public virtual IActionResult PasswordRecoveryConfirmView(string token, Guid guid)
        {
            var customer = _customerService.GetCustomerByGuid(guid);
            if (customer == null)
                return RedirectToRoute("HomePage");
            var recoverConfirmModel = _customerModelFactory.PreparePasswordRecoveryConfirmModel(customer.Id, token);
                        
            //validate token
            if (!_customerService.IsPasswordRecoveryTokenValid(customer, token))
            {
                recoverConfirmModel.DisablePasswordChanging = true;
                recoverConfirmModel.Result = WebApi.ApiResponseMessages.PasswordRecoveryTokenNotAvalable;
                return View(recoverConfirmModel);
            }

            //validate token expiration date
            if (_customerService.IsPasswordRecoveryLinkExpired(customer))
            {
                recoverConfirmModel.DisablePasswordChanging = true;
                recoverConfirmModel.Result = WebApi.ApiResponseMessages.PasswordRecoveryTokenExpired;
            }

            return View(recoverConfirmModel);
        }
        #endregion

        #endregion
    }
}
